#include "src/ltb_dep.h"
#include <string.h>
#include "src/ltlog.h"

bool
ltb_FindTarget(ltb_Config* cfg, char const* name, uint32_t* id) {
    lta_ForEach(i, cfg->targets) {
        Target const* each_target = &cfg->targets.data[i];

        if (strcmp(each_target->name, name) == 0) {
            *id = i;
            return true;
        }
    }

    return false;
}

static bool
CollectDeps_Each(ltb_Config* cfg, Target const* target, lta_U32Arr* deps,
                 char const* dep_name) {
    uint32_t target_id = 0;
    if (!ltb_FindTarget(cfg, dep_name, &target_id)) {
        ltlog_Log2(Error, "undefined dep of target",
                   "dep name", String(dep_name),
                   "target name", String(target->name));
        return false;
    }

    bool found = false;
    lta_ForEach(i, *deps) {
        if (deps->data[i] == target_id) {
            found = true;
            break;
        }
    }

    if (!found)
        lta_Append(*deps, target_id);

    if (!ltb_CollectDeps(cfg, &cfg->targets.data[target_id], deps, ltb_NotTop))
        return false;

    return true;
}

/**收集目标的依赖。

收集cfg中target的依赖，包括依赖的依赖，把它们的下标追加到deps数组中。每个依赖只被追加一次。

目标的public_dep会视作target的依赖，而如果top_type为ltb_IsTop，那么secret_dep也是依赖。
*/
bool
ltb_CollectDeps(ltb_Config* cfg, Target const* target, lta_U32Arr* deps,
                ltb_TopType top_type) {
    if (top_type == ltb_IsTop) {
        lta_ForEach(i, target->secret_deps) {
            if (!CollectDeps_Each(cfg, target, deps,
                                  target->secret_deps.data[i]))
                return false;
        }
    }

    lta_ForEach(i, target->public_deps) {
        if (!CollectDeps_Each(cfg, target, deps, target->public_deps.data[i]))
            return false;
    }
    return true;
}
